<?php
namespace apis;
use enums\RetCodeEnums;
use apps\common\controllers\DLockController;
if( ! APP_ROOT  ) return 'Direct Access Deny!';

class DLockUtils implements \Phalcon\DI\InjectionAwareInterface
{ 
	const URL_CTRL = '/common/dlock/';
	
	/**
	 * 强制初始化（强制覆盖原有值，自行处理善后）
	 */
	const INIT_FORCE = 1;
	
	/**
	 * 非强制初始化 （有则返回剩余资源量，无则直接初始化）
	 */
	const INIT_FORCE_NONE = 2;
	
	static private $_instance = null;
	
	private $_di = null;
	private $_strUrl = null; 
	
	/* 
	 * @see \Phalcon\Di\InjectionAwareInterface::setDI()
	 */
	public function setDI( \Phalcon\DiInterface $dependencyInjector ) 
	{
		$this->_di = $dependencyInjector;	
	}

	/**
	 * 取server url
	 * @return string
	 */
	private function getServerUrl()
	{
		if( !$this->_strUrl )
		{
			$this->_strUrl = $this->_di[ 'urlCfg' ]->url->url_lct_domain . self::URL_CTRL . '/';
		}
		
		return $this->_strUrl;
	}
	
	private function __construct( $di = null )
	{
		$this->setDI( $di );
	}
	
	public static function getInstance( $di = null )
	{
		if( is_null( self::$_instance ))
		{
			self::$_instance = new DLockUtils($di );
		}	
		
		return self::$_instance;
	}
	
	/* 
	 * @see \Phalcon\Di\InjectionAwareInterface::getDI()
	 */
	public function getDI() 
	{
		return $this->_di;
	}
	
	private function getResult( string $strUrl )
	{
		try
		{
			$curl = curl_init( $strUrl );
			curl_setopt( $curl, CURLOPT_TIMEOUT, 10 );
			curl_setopt( $curl, CURLOPT_HEADER, 0 );
			curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 );
			$strRet = curl_exec( $curl );
			curl_close( $curl );
		}
		catch ( \Exception $e )
		{
			return array( 
					'code' => RetCodeEnums::ERR_NETWORK, 
					'msg' => RetCodeEnums::ERR_NETWORK_MSG  );
		}
		
		return json_decode( $strRet );
	}
	
	/**
	 * status: done
	 * 初始化锁
	 * @param string $strLockName 资源锁名
	 * @param int $iResID 资源ID
	 * @param int $iBase 初始加锁时的资源
	 *
	 * return false：错误 int:未消费的资源数
	 */
	public function initLock( string $strLockName, int $iResID, int $iBase = 100, $iForce = self::INIT_FORCE_NONE )
	{
		if( !$strLockName || trim( $strLockName ) == '' || 
			$iResID <= 0 ||
			$iBase <= 0 )
		{
			return array( 
					'code' => RetCodeEnums::ERR_PARAMS, 
					'msg' => RetCodeEnums::ERR_PARAMS_MSG  );
		}
		
		$strUrl = $this->getServerUrl() . __FUNCTION__ . 
				'/lname/' . $strLockName . 
				'/rid/'. $iResID . 
				'/base/' . $iBase . 
				'/force/' . $iForce;

		return $this->getResult( $strUrl );
	}
	
	/**
	 * @comment 取剩余的资源数量
	 * 剩余的资源数量 = 总资源量 - 消费的资源量
	 * @param string $strLockName
	 * @param int $iResID
	 *
	 * return false for error int for resource left
	 */
	public function getResLeftCnt( string $strLockName, int $iResID )
	{
		if( !$strLockName || trim( $strLockName ) == '' ||
			$iResID <= 0 )
		{
			return array(
					'code' => RetCodeEnums::ERR_PARAMS,
					'msg' => RetCodeEnums::ERR_PARAMS_MSG  );
		}
		
		$strUrl = $this->getServerUrl() . __FUNCTION__ . '/lname/' . $strLockName . '/rid/'. $iResID;
		
		return $this->getResult( $strUrl );
	}
	
	/**
	 * 取初始资源总量
	 * @param $strLockName
	 * @param $iResID
	 *
	 * return false for error others for success
	 */
	public function getResInitCnt( string $strLockName, int $iResID )
	{
		if( !$strLockName || trim( $strLockName ) == '' ||
			$iResID <= 0 )
		{
			return array(
					'code' => RetCodeEnums::ERR_PARAMS,
					'msg' => RetCodeEnums::ERR_PARAMS_MSG  );
		}
		
		$strUrl = $this->getServerUrl() . __FUNCTION__ . '/lname/' . $strLockName . '/rid/'. $iResID;
		
		return $this->getResult( $strUrl );
	}
	
	/**
	 * 取资源使用情况
	 * 返回资源的初始值， 未消费资源量， 资源名， 资源ID
	 * 此接口主要用于前端显示规格之类的销售情况
	 *
	 * return array for success false for error
	 */
	public function getResStatus( string $strLockName, int $iResID )
	{
		if( !$strLockName || trim( $strLockName ) == '' ||
			$iResID <= 0  )
		{
			return array(
					'code' => RetCodeEnums::ERR_PARAMS,
					'msg' => RetCodeEnums::ERR_PARAMS_MSG  );
		}
		
		$strUrl = $this->getServerUrl() . __FUNCTION__ . '/lname/' . $strLockName . '/rid/'. $iResID;
		
		return $this->getResult( $strUrl );
	}
	
	/**
	 * @param string $strLockName 资源名
	 * @param int $iResID 资源ID
	 * @param int $iApplicantID 资源的申请者ID
	 * @param int $iRequestNum 需要的资源数量
	 * @param int $holdSeconds
	 * @return boolean
	 */
	public function lockRes( string $strLockName, int $iResID, $iApplicantID, $iRequestNum, $iHoldSeconds = 100 )
	{
		if( !$strLockName || trim( $strLockName ) == '' ||
			$iResID <= 0 ||
			$iApplicantID <= 0 || 
			$iRequestNum <= 0 ||
			$iHoldSeconds <= 0 )
		{
			return array(
					'code' => RetCodeEnums::ERR_PARAMS,
					'msg' => RetCodeEnums::ERR_PARAMS_MSG  );
		}
		
		$strUrl = $this->getServerUrl() . __FUNCTION__ . '/lname/' . $strLockName . 
					'/rid/'. $iResID . 
					'/aid/' . $iApplicantID .
					'/rnum/' . $iRequestNum . 
					'/seconds/' . $iHoldSeconds;
		
		return $this->getResult( $strUrl );
	}
	
	/**
	 * status: to be done
	 * @param string $strLockName
	 * @param int $iID
	 *
	 * return true for success others for error
	 */
	public function unlockRes( string $strLockName, int $iResID, int $iApplicantID )
	{//
		if( !$strLockName || trim( $strLockName ) == '' ||
			$iResID <= 0 ||
			$iApplicantID <= 0 )
		{
			return array(
					'code' => RetCodeEnums::ERR_PARAMS,
					'msg' => RetCodeEnums::ERR_PARAMS_MSG  );
		}
		
		$strUrl = $this->getServerUrl() . __FUNCTION__ . '/lname/' . $strLockName .
					'/rid/'. $iResID .
					'/aid/' . $iApplicantID;
		
		return $this->getResult( $strUrl );
	}
	
	/**
	 * 删除资源锁
	 * @param string $strLockName
	 * @param int $iResID
	 * @return number
	 */
	public function delLock( string $strLockName, int $iResID )
	{
		if( !$strLockName || trim( $strLockName ) == '' ||
			$iResID <= 0 )
		{
			return array(
					'code' => RetCodeEnums::ERR_PARAMS,
					'msg' => RetCodeEnums::ERR_PARAMS_MSG  );
		}
		
		$strUrl = $this->getServerUrl() . __FUNCTION__ . '/lname/' . $strLockName .
					'/rid/'. $iResID;
		
		return $this->getResult( $strUrl );
	}
	
	/**
	 * 消费资源
	 * @param string $strLockName
	 * @param int $iResID
	 * @param int $iApplicantID
	 *
	 * return true for success others for error
	 */
	public function consume( string $strLockName, int $iResID, int $iApplicantID )
	{
		if( !$strLockName || trim( $strLockName ) == '' ||
			$iResID <= 0 ||
			$iApplicantID <= 0 )
		{
			return array(
					'code' => RetCodeEnums::ERR_PARAMS,
					'msg' => RetCodeEnums::ERR_PARAMS_MSG  );
		}
		
		$strUrl = $this->getServerUrl() . __FUNCTION__ . '/lname/' . $strLockName .
				'/rid/'. $iResID .
				'/aid/' . $iApplicantID;
		
		return $this->getResult( $strUrl );
	}
	
	/**
	 * 取资源申请者及其申请的资源量
	 *
	 * @param string $strLockName
	 * @param int $iResID
	 * @return int for error object for success
	 */
	public function getApplicants( string $strLockName, int $iResID )
	{
		if( !$strLockName || trim( $strLockName ) == '' ||
			$iResID <= 0  )
		{
			return array(
					'code' => RetCodeEnums::ERR_PARAMS,
					'msg' => RetCodeEnums::ERR_PARAMS_MSG  );
		}
		
		$strUrl = $this->getServerUrl() . __FUNCTION__ . '/lname/' . $strLockName .
					'/rid/'. $iResID;
		
		return $this->getResult( $strUrl );
	}
	
	/**
	 * 剩余的未加锁的资源与剩余的资源总量
	 * @param $strLockName
	 * @param $iResID
	 *
	 * array for success int for error e.g.
	 * object( public 'locked' => 11, public 'left' => '17' )
	 */
	public function getNoneLockedRes( string $strLockName, int $iResID )
	{
		if( !$strLockName || trim( $strLockName ) == '' ||
			$iResID <= 0  )
		{
			return array(
					'code' => RetCodeEnums::ERR_PARAMS,
					'msg' => RetCodeEnums::ERR_PARAMS_MSG  );
		}
		
		$strUrl = $this->getServerUrl() . __FUNCTION__ . '/lname/' . $strLockName .
					'/rid/'. $iResID;
		
		return $this->getResult( $strUrl );
	}
	
}